//
//  ZipManager.swift
//

import Zip
import Alamofire
import CleanJSON

class ZipManager: NSObject {
    static let share = ZipManager()
    /// 下载zip包的存放路径
    private let bookZipFilePath = NSHomeDirectory() + "/Documents/BookZip/"
    /// 解压zip包的存放路径
    private let bookUnzipFilePath = NSHomeDirectory() + "/Documents/BookUnzip/"
    
    /// 下载并解压
    /// - Parameters:
    ///   - url: 下载链接
    ///   - downloadProgress: 下载进度回调
    ///   - unzipProgress: 解压进度回调
    ///   - response: 数据模型回调
    ///   - failure: 错误回调
    func downloadZipHandler(_ url: String,
                            downloadProgress: @escaping (Progress) -> Void,
                            unzipProgress: @escaping (Double) -> Void,
                            response: @escaping (BookModel?) -> Void,
                            failure: @escaping (AppError) -> Void) {
        /// 根据url判断文件是否存在，如果存在直接去取，否则去下载
        if isExistence(url: url) {
            response(getBook(url))
            return
        }
        /// 配置下载的存放路径
        let destination: DownloadRequest.Destination = { _, _ in
            let filePath = self.bookZipFilePath + url.MD5String + url.pathExtension
            let fileURL = URL(fileURLWithPath: filePath)
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        /// 开始下载
        NetworkManager.share.download(url, to: destination) { progress in
            downloadProgress(progress)
        } responseURL: { responseURL in
            debugPrint(responseURL)
            /// 下载完成后解压，responseURL就是上面配置的下载的存放路径
            self.unzip(responseURL,
                       downloadURL: url,
                       unzipProgress: unzipProgress,
                       response: response,
                       failure: failure)
        } failure: { error in
            failure(error)
        }
    }
    
    /// 解压
    /// - Parameters:
    ///   - url: zip包的存放位置
    ///   - downloadURL: zip包的下载链接，作为解压文件的文件夹名称
    ///   - unzipProgress: 解压进度回调
    ///   - response: 数据模型回调
    ///   - failure: 错误回调
    private func unzip(_ url: URL,
                       downloadURL: String,
                       unzipProgress: @escaping (Double) -> Void,
                       response: @escaping (BookModel?) -> Void,
                       failure: @escaping (AppError) -> Void) {
        let filePath = bookUnzipFilePath + downloadURL.MD5String
        let fileURL = URL(fileURLWithPath: filePath)
        do {
            try Zip.unzipFile(url, destination: fileURL, overwrite: true, password: nil, progress: { progress in
                unzipProgress(progress)
                if progress >= 1 {
                    response(self.getBook(downloadURL))
                    self.deleteFile(url: downloadURL)
                }
            })
        } catch {
            print("解压失败")
            failure(AppError(code: -1, errorMessage: error.localizedDescription))
        }
    }
    
    /// 判断该文件是否存在
    private func isExistence(url: String) -> Bool {
        let fileName = url.MD5String
        do {
            let files = try FileManager.default.contentsOfDirectory(atPath: bookUnzipFilePath)
            return files.contains(fileName)
        } catch {
            return false
        }
    }
    
    /// 获取绘本模型
    private func getBook(_ url: String) -> BookModel? {
        guard let u = URL(string: url) else {
            return nil
        }
        let lastFileDocuments = u.lastPathComponent.replacingOccurrences(of: ".zip", with: "")
        let allPath = bookUnzipFilePath + url.MD5String + "/\(lastFileDocuments)/"
        let indexPath = allPath + "index.json"
        do {
            let indexData = try Data(contentsOf: URL(fileURLWithPath: indexPath))
            if var bookModel = try? CleanJSONDecoder().decode(BookModel.self, from: indexData) {
                bookModel.coverURL = allPath + bookModel.cover
                bookModel.downloadURL = url
                for (index, model) in bookModel.pagesv2.enumerated() {
                    bookModel.pagesv2[index].imageURL = allPath + model.bac
                    bookModel.pagesv2[index].audioURL = allPath + model.audio
                }
                return bookModel
            }
            return nil
        } catch {
            return nil
        }
    }
    
    /// 根据url删除zip文件
    private func deleteFile(url: String) {
        let filePath = bookZipFilePath + url.MD5String + url.pathExtension
        do {
            try FileManager.default.removeItem(atPath: filePath)
        } catch {}
    }
}

struct BookModel: Codable {
    let audioMode: String
    let cover: String
    let name: String
    let pageCount: Int
    var pagesv2: [BookPageModel]
    let portrait: Bool
    let read: String
    let version: String
    var coverURL: String
    var downloadURL: String
}

struct BookPageModel: Codable {
    let audio: String
    let bac: String
    let p: Int
    let time: String
    var imageURL: String
    var audioURL: String
}
